package com.cdtu.utils;

import com.cdtu.NettyServer;
import com.cdtu.vo.ChannelHandlerContextVo;
import io.netty.buffer.Unpooled;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelHandlerContext;
import io.netty.util.internal.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;

import java.net.InetSocketAddress;
import java.time.Duration;
import java.time.Instant;
import java.util.Arrays;
import java.util.Map;

/**
 * @author Mika
 * @date 2025/03/01 12:07
 **/
@Slf4j
public class NetUtils {
    // 绑定参数
    public static ChannelHandlerContextVo bindParams(ChannelHandlerContext ctx) {
        InetSocketAddress address = (InetSocketAddress) ctx.channel().remoteAddress();
        String reqIp = address.toString();
        String clientHost = address.getAddress().getHostAddress();
        int clientPort = address.getPort();
        String clientId = ctx.channel().id().asShortText();

        return ChannelHandlerContextVo.builder()
                .clientIdToShort(clientId)
                .reqIp(reqIp)
                .host(clientHost)
                .port(clientPort)
                .build();
    }

    // 条件是包含 channels 的 key，即 ip
    public static void sendStringToClients(String condition, String[] message) {
        byte[] bytes = Crc16Utils.getByteData(message);
        sendToClients(condition, bytes, message);
    }

    // 向符合条件的客户端发送消息
    public static void sendToClients(String condition, byte[] message, String[] sourceMessage) {
        for (Map.Entry<String, Channel> entry : NettyServer.channels.entrySet()) {
            log.debug("channels.key: {}, condition: {}", entry.getKey(), condition);
            if (entry.getKey().contains(condition)) {
                Channel channel = entry.getValue();
                InetSocketAddress inetSocketAddress = (InetSocketAddress) channel.remoteAddress();
                // 这里才是真实的 channel ip，port 连接
                log.debug("向 {}:{} 发送消息: {}",
                        inetSocketAddress.getHostName(), inetSocketAddress.getPort(), Arrays.toString(sourceMessage));
                //
                Instant start = Instant.now();
                ChannelFuture channelFuture = entry.getValue()
                        .writeAndFlush(Unpooled.wrappedBuffer(message));
                try {
                    channelFuture.sync();
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
                Instant end = Instant.now();
                long costTime = (Duration.between(start, end).toMillis());
                log.debug("id-{} ==> send order cost time {}ms", channel.id().asShortText(), costTime);
            }
        }
    }
}
